/*
 *  SpecialLinkedList11.cpp
 *  SpecialLinkedList11
 *
 *  Created by Hamza SHAWY on 07-11-26.
 *  Copyright 2007 __MyCompanyName__. All rights reserved.
 *
 */

#include "SpecialLinkedList1.h"


//Definition of the constructor of the SpecialLinkedList1 class (from the "mother" class)
SpecialLinkedList1::SpecialLinkedList1():SpecialLinkedList() 
{
}


//hey


/*Definition of the destructor of the class SpecialLinkedList1*/
SpecialLinkedList1::~SpecialLinkedList1()
{
	if(useDebug) cout << "destructor called for"<< this << endl;
}





/*Definition of the overloading member funtion "operator=" of the class SpcialLinkedList*/
SpecialLinkedList1& SpecialLinkedList1::operator=(SpecialLinkedList1 other)
{
	//see operator+ to understand why there is this commented thing
// 	SpecialLinkedList1* wontDisappear = new SpecialLinkedList1();
// 	if(useDebug) cout << "operator= called for"<<this << "=" << &other << endl;
// 	wontDisappear->addAll(&other);
// 	if(useDebug) cout << "operator=: other is as"<< endl;
// 	if(useDebug) other.print();
// 	if(useDebug) cout << "operator=: me is as" << endl;
// 	if(useDebug) wontDisappear->print();
// 	return *wontDisappear;
// 	SpecialLinkedList1 ob;
// 	ob.addAll(&other);
// 	return ob; //note: if we return a SpecialLinkedList1& , there is this warning : SpecialLinkedList1.cpp:44: warning: reference to local variable ‘ob’ returned
// 	//so we return a normal SpecialLinkedList1 with no & after
	clear();
	cout << "operator=: other is";
	other.print();
	addAll(&other);
	cout << "after eating its items:";
	other.print();
	return *this;
}






/*Definition of the overloading member funtion "operator+" of the class SpcialLinkedList*/
//expressions L1 = L2+L3 whether L1 is initialized at that moment or not(ie: SpecialLinkedList1(with or without &) L1=L2+L3)

//one pb: doing L1+L2 in the void may create leaked memory if we're allocating something ourselves here...
SpecialLinkedList1 operator+(SpecialLinkedList1& left, SpecialLinkedList1& right)
{
// 	SpecialLinkedList1* ob=new SpecialLinkedList1();
// 	ob->addAll(this);
// 	ob->addAll(&other);
// // 	cout << "operator+ :";
// 	//ob->print();
// 	return *ob;
	SpecialLinkedList1 ob;
	ob.addAll(&left);
	ob.addAll(&right);
	return ob;
}




/*Definition of the overloading member funtion "operator-" of the class SpcialLinkedList*/
SpecialLinkedList1 operator-(SpecialLinkedList1& left, SpecialLinkedList1& right)
{
	/* Note that the functions "addAll" and "removeAll" are supposed safe
	We consider that if A is empty and B is not empty, doing A - B keeps giving an empty list
	thus without raising any error */
	
//see operator+ & operator= for details
// 	SpecialLinkedList1* ob = new SpecialLinkedList1();
// // 	ob->enableDebug();
// 	if(useDebug) cout << "operator- called for" << this << " - " << &other << endl;
// 	if(useDebug) cout << "operator- before addAll" << endl;
// 	ob->addAll(this);
// 	if(useDebug) cout << "operator- after addAll" << endl;
// 	if(useDebug) cout << "operator- before removeAll" << endl;
// 	ob->removeAll(&other);
// 	if(useDebug) cout << "operator- after removeAll" << endl;
// 	if(useDebug) cout << "operator- returns reference/pointer:" << &ob << "which is:"<<endl;
// 	if(useDebug) ob->print();
// 	return *ob;
	SpecialLinkedList1 ob;
	ob.addAll(&left);
	ob.removeAll(&right);
	return ob;
}


/*Definition of the overloading member funtion "operator==" of the class SpcialLinkedList*/
bool SpecialLinkedList1::operator==(SpecialLinkedList1& other) 
{
	if(size() != other.size())  //if the size of both lists is not the same, then the function returns false.
		return false;
	
	for(int a=0;a<size();a++)  /* if the size of both the lists is the same but the elements are not followed in the same manner in the two lists, 
	                              then the function returns false */
	if(!contains(other[a]))            
			return false;
	
	return true;
}





/*Definition of the overloading member funtion "operator[]" of the class SpcialLinkedList*/
int SpecialLinkedList1::operator[](int index) 
{
	return SpecialLinkedList::operator [](index);
}






/*Definition of the overloading member funtion "operator<<" of the class SpcialLinkedList*/
ostream& operator<<(ostream& out, SpecialLinkedList1& other) ////for cout << SpecialLinkedList1_instance,returns true if the list not empty, false if it is (empty)
{
	if(other.isEmpty())
	{
		out << "<SpecialLinkedList1 instance at " << &other << ">" << endl << "no items"<<endl;
	}
	else
	{
		out << "<SpecialLinkedList1 instance at " << &other << ">" << endl;
		for(int a=0;a<other.size();a++)
		{
			out << other[a] << ";" << endl;
		}
	}
	out << "</SpecialLinkedList1>" << endl;
	return out;

}

/*Definition of the overloading member funtion "operator>>" of the class SpcialLinkedList*/
//Regarding the function : cin >> SpecialLinkedList1_instance
		/* Asks the user to enter integers to fill the list, then :
		1) If user provided only integers, it returns true, and fills the list with them
		2) Else, it returns false, and does not fill the list */
istream& operator>>(istream& in, SpecialLinkedList1& other)  
{
	//variables
	int whatToAdd; //integer to insert into other.add(INT)
	int indexOfLetterFound; //pos of y or n or none if find_first_of did not find anything
	string lineWithLetter; //string that'll receive y,n or p or anything to know if the user wants to keep adding numbers
	string tmp;
	bool cinWorked; //set to false if the entered number isn't an actual number.. produces error to be set to true
	bool error=false; //set to true in case the entered integer isn't actually an integer
	bool noMoreAdding=false; //set to true by the user when he wants to stop adding numbers => makes the program leave the two while loops in the function
	bool didUnderstand=false; //set to true if the line input meant to contain y, n, or p or nothing did contain any of those
	bool printListEachTime = false; //set to true/false if user enabled printing the list after each addition using letter "p" in the "continue?" question
	bool changedPrintingSetting = false; //set to true when printing has just been enabled so we can run a blank loop any info/question on numbers added/to add
	
	//function start
	cout << "[- Interactive element adder of <SpecialLinkedList1 instance at "<<&other<<"> -]" << endl << "--You can type \"p\" between each appending"<< endl << "  to enable/disable printing of the list."<<endl<<endl;
	cout << "initial situation is:" << endl << other << endl;
	//outer loop: the one loop were asking for a number to add & printing the list take place
	do
	{
		//if last user entry wasn't a number, tell to the user he did something wrong
		if(error)
		{
			cout << "error: your entry should start with some integer value." << endl;
			error = false;
		}
		//
		if(!changedPrintingSetting)
		{
			cout << "type an integer to append: ";
			getline(cin,tmp);
			istringstream hop(tmp);
			cinWorked = (hop >> whatToAdd);
		}
		//if couln't eat an integer
		if(!cinWorked)
		{
			error = true;
		}
		//if could eat an integer
		else
		{
			//if we did not change the printing settings that's to say, we're not doing a loop because a number was added just before
			if(!changedPrintingSetting)
			{
				cout << "added " << whatToAdd << " to list" << endl; //TODO use list.add(a) here
				other.add(whatToAdd);
			}
			else
				changedPrintingSetting = false;
			//if printing the list is enabled
			if(printListEachTime)
				cout << other;
			//ask if want to keep adding integers or not
			//this loop keeps executing as long as the user did not type something either: empty,
			do
			{
				//taking user input as to what he wants to do now
				cout << "do you want to keep adding ? (y/n/p) [default:y] ";
				//eats any line into string letter, including the \n
				getline(cin,lineWithLetter);
				
				//analysis of the user choice
				//to leave this function we must have the only letter understood in the user input to be n
				indexOfLetterFound = lineWithLetter.find_first_of("pyn");
				//if we "did" recognize letters in user input, or the user input was nothing or the user input only contained spaces
				didUnderstand = (indexOfLetterFound != -1 || (lineWithLetter.length() == 0 || (unsigned int)count(lineWithLetter.begin(),lineWithLetter.end(),' ') == lineWithLetter.length()));
				noMoreAdding = (didUnderstand && indexOfLetterFound != -1 && lineWithLetter[indexOfLetterFound] == 'n');
				
				//if the user just asked to enable/disable the printing of the list we're editing
				//we also do the necessary so that things about adding number above in the loop won't get executed next time
				//by setting changedPrintingSetting to true
				if(indexOfLetterFound != -1 && lineWithLetter[indexOfLetterFound] == 'p')
				{
					printListEachTime = !printListEachTime;
					changedPrintingSetting = true;
					cout << "printing the list each time: "<< (printListEachTime ? "enabled." : "disabled.") << endl;
                //didUnderstand = false; //small hack to do the loop again
				}
			}
			while(!didUnderstand);
		}
        //if(noMoreAdding)
        //cout << "you chose to stop adding" << endl;
	}while(error || !noMoreAdding);
	cout << "-- Interactive element adder: done. --" << endl;
	return in;
}
